package org.alis.ap.rpc.server.server;

import lombok.extern.slf4j.Slf4j;
import org.alis.ap.rpc.Request;
import org.alis.ap.rpc.Response;
import org.alis.ap.rpc.codec.Decoder;
import org.alis.ap.rpc.codec.Encoder;
import org.alis.ap.rpc.server.ServiceInvoker;
import org.alis.ap.rpc.server.config.ServerConfig;
import org.alis.ap.rpc.server.manager.ServiceManager;
import org.alis.ap.rpc.transport.TransportServer;
import org.alis.ap.rpc.utils.ReflectionUtils;
import org.apache.commons.io.IOUtils;

import java.io.IOException;

/**
 * ApServer desc:
 *
 * @author luochuan
 * @date 2020/10/16 17:42
 */
@Slf4j
public class ApRpcServer {

    public ApRpcServer(){
        this(new ServerConfig());
    }

    public ApRpcServer(ServerConfig serverConfig) {
        this.serverConfig = serverConfig;
        // net
        this.transportServer = ReflectionUtils.newInstance(serverConfig.getClazz());
        this.transportServer.init(serverConfig.getPort(),(in,out)->{
            Response<Object> response = new Response<>();
            try {
                byte[] bytes = IOUtils.readFully(in, in.available());
                Request request = decoder.decode(bytes, Request.class);
                log.info("获取到请求:",request);
                Object invoke = serviceInvoker.invoke(serviceManager.lookup(request), request);
                response.setData(invoke);
            } catch (Exception e) {
                log.warn(e.getMessage(),e);
                response.setCode(1);
                response.setMessage("RpcService got error"+e.getClass().getName()+":"+e.getMessage());
            }finally {
                byte[] encode = encoder.encode(response);
                try {
                    out.write(encode);
                    log.info("response over");
                } catch (IOException e) {
                    log.warn(e.getMessage(),e);
                }
            }
        });
        this.encoder = ReflectionUtils.newInstance(serverConfig.getEncoderClass());
        this.decoder = ReflectionUtils.newInstance((Class<Decoder<Request>>) serverConfig.getDecoderClass());
        this.serviceManager = new ServiceManager();
        this.serviceInvoker = new ServiceInvoker();
    }

    private ServerConfig serverConfig;
    private TransportServer transportServer;
    private Encoder encoder;
    private Decoder<Request> decoder;
    private ServiceManager serviceManager;
    private ServiceInvoker serviceInvoker;


    public void register(Class interfaceClass,Object bean){
        serviceManager.register(interfaceClass,bean);
    }

    public void start(){
        this.transportServer.start();
    }

    public void stop(){
        this.transportServer.stop();
    }
}
